//===----------------------------------------------------------------------===//
//
//                         BusTub
//
// tuple.h
//
// Identification: src/include/storage/table/tuple.h
//
// Copyright (c) 2015-2019, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#pragma once

#include <string>
#include <utility>
#include <vector>
#include <type/value.h>
#include <memory>

#include "common/rid.h"
#include "catelog/table.h"

namespace benxdb {

/**
 * Tuple format:
 * ---------------------------------------------------------------------
 * | FIXED-SIZE or VARIED-SIZED OFFSET | PAYLOAD OF VARIED-SIZED FIELD |
 * ---------------------------------------------------------------------
 */
class Tuple {
  friend class DataPage;

public:
    // Default constructor (to create a dummy tuple)
    Tuple() = default;
    ~Tuple();

    // constructor for table heap tuple
    explicit Tuple(record_id_t record_id) : record_id_(record_id) {}

    // constructor for creating a new tuple based on input value
    explicit Tuple(const std::vector<Value>& values);

    // constructor for creating a new tuple based on table
    explicit Tuple(uint32_t size);

    explicit Tuple(std::iostream& io, uint32_t size);

    Tuple(Tuple &&tuple)  noexcept ;

    Tuple(const Tuple& tuple);

    // constructor for creating a new tuple based on table
    explicit Tuple(char *data, uint32_t size);

    explicit Tuple(record_id_t rid, const std::vector<Value>& values);

    // return RID of current tuple
    [[nodiscard]] record_id_t GetRid() const { return record_id_; }

    // Get the value of a specified column (const)
    // checks the schema to see how to return the Value.
    void GetValue(const Column &column, Value& val) const;

    inline char *GetData() const {
      return values_;
    }

    inline uint32_t GetSize() const {
      return size_;
    }

    void AppendValue(const Column& column, const Value& value);

    void AppendData(const Column& column, char* data);

    void ReadData(std::iostream& io);

private:
    record_id_t record_id_{};
    char* values_{};
    uint32_t size_{};
};

}  // namespace bustub
